import { WebSocketServer, WebSocket } from "ws";
import { Connection } from "./Connection";
import { ApiMsgEnum, IModel } from "../Common";
import { EventEmitter } from "stream";

export class MyServer extends EventEmitter {
  port: number;
  wss: WebSocketServer;

  apiMap: Map<ApiMsgEnum, Function> = new Map<ApiMsgEnum, Function>();
  connections: Set<any> = new Set();

  constructor({ port }: { port: number }) {
    super();
    this.port = port;
  }

  setApi<T extends keyof IModel["api"]>(
    name: T,
    cb: (connection: Connection, args: IModel["api"][T]["req"]) => void
  ) {
    this.apiMap.set(name, cb);
  }

  async start() {
    return new Promise((resolve, reject) => {
      this.wss = new WebSocketServer({ port: this.port });

      this.wss.on("connection", (ws: WebSocket) => {
        let newConnection = new Connection(this, ws);

        this.connections.add(newConnection);

        this.emit("connection", newConnection);

        newConnection.on("close", () => {
          this.connections.delete(newConnection);
          this.emit("disconnection", newConnection);
        });
      });

      this.wss.on("error", (e) => {
        reject(false);
      });

      this.wss.on("close", () => {
        reject(false);
      });

      this.wss.on("listening", () => {
        console.log("listening");
        resolve(true);
      });
    });
  }
}
